    using UnityEngine;
    using System.Collections;
     
/**
 * Script of camera behaviour description (replay mode).
 * The purpose of this class is to manage the replay camera.
 * The target will be a GameObject.
 * @author Benjamin Bruneau 
 */
public class ReplayCameraScript : MonoBehaviour
{
	private float _x = 0.0f; //  Position
	private float _y = 45f; // Position
	private float _currentDistance; // Current distance
	private float _desiredDistance; // Desired distance
	private float _correctedDistance; // Corrected distance
 	
	public GameObject _pauseManager; // Pause manager GameObject
	
	public Transform _target; // Camera's target
	
	public float _targetHeight = 1.7f; // height
	public float _distance = 15.0f; //Base distance
	public float _maxDistance = 20; // Max distance
	public float _minDistance = 0.6f; // Min distance
	public float _xSpeed = 120.0f; // Mouse sensivity
	public float _ySpeed = 120.0f; // Mouse sensivity
	public float _zoomDampening = 5.0f; // Zoom speed
	
	public int _yMinLimit = -80; // Top max
	public int _yMaxLimit = 80; // Bottom Max
	public int _zoomRate = 50; // Zoom rate
	 
	/**
	 * Called on initialization.
	 * @return void
	 */
	void Start ()
	{		
		// Initialization of distances
		_currentDistance = _distance;
		_desiredDistance = _distance;
		_correctedDistance = _distance;    
	}
       
	/**
	 * Called every frame if the behaviour is enabled.
	 * @return void
	 */
	void LateUpdate ()
	{    
		// If not on pause
		if (!_pauseManager.GetComponent<PauseControllerScript> ()._pause) 
		{
			// Update
			_x += Input.GetAxis ("Mouse X") * _xSpeed * 0.02f;
			_y -= Input.GetAxis ("Mouse Y") * _ySpeed * 0.02f;
			_y = ClampAngle (_y, _yMinLimit, _yMaxLimit);
     
			// Set camera rotation
			Quaternion rotation = Quaternion.Euler (_y, _x, 0);
     
			// Calculate the desired distance
			_desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * _zoomRate * Mathf.Abs (_desiredDistance);
			_desiredDistance = Mathf.Clamp (_desiredDistance, _minDistance, _maxDistance);
			_correctedDistance = _desiredDistance;
     
			// Calculate desired camera position
			Vector3 position = _target.position - (rotation * Vector3.forward * _desiredDistance + new Vector3 (0, -_targetHeight, 0));
     
			// Check for collision using the true target's desired registration point as set by user using height
			RaycastHit collisionHit;
			Vector3 trueTargetPosition = new Vector3 (_target.position.x, _target.position.y + _targetHeight, _target.position.z);
     
			// If there was a collision, correct the camera position and calculate the corrected distance
			bool isCorrected = false;
			if (Physics.Linecast (trueTargetPosition, position, out collisionHit)) 
			{
				position = collisionHit.point;
				_correctedDistance = Vector3.Distance (trueTargetPosition, position);
				isCorrected = true;
			}
           
			// For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance
			_currentDistance = !isCorrected || _correctedDistance > _currentDistance ? Mathf.Lerp (_currentDistance, _correctedDistance, Time.deltaTime * _zoomDampening) : _correctedDistance;
     
			// Recalculate position based on the new currentDistance
			position = _target.position - (rotation * Vector3.forward * _currentDistance + new Vector3 (0, -_targetHeight, 0));
     
			//Apply
			transform.rotation = rotation;
			transform.position = position;
		
		}
	}
     
	/**
	 * Clamping angle method.
	 * @param float, float, float
	 * @return float
	 */
	private static float ClampAngle (float angle, float min, float max)
	{
		if (angle < -360)
			angle += 360;
		if (angle > 360)
			angle -= 360;
		return Mathf.Clamp (angle, min, max);
	}
}